#!/usr/bin/env python
# -*- coding: UTF-8 -*-

'''
Copyright (C) 2009 dbzhang800@gmail.com
All rights reserved.
''' 

from ctypes import *
from ctypes.wintypes import *

NULL = 0
INVALID_HANDLE_VALUE = -1
DIGCF_PRESENT = 0x00000002
DIGCF_ALLCLASSE = 0x00000004
SPDRP_DEVICEDESC = 0
SPDRP_HARDWAREID = 1
NO_ERROR = 0
ERROR_INSUFFICIENT_BUFFER = 122
ERROR_NO_MORE_ITEMS = 259

setupapi = windll.setupapi
SetupDiGetClassDevs = setupapi.SetupDiGetClassDevsW
SetupDiEnumDeviceInfo = setupapi.SetupDiEnumDeviceInfo
SetupDiGetDeviceRegistryProperty = setupapi.SetupDiGetDeviceRegistryPropertyW
SetupDiDestroyDeviceInfoList = setupapi.SetupDiDestroyDeviceInfoList

class GUID(Structure):
    _fields_ = [("Data1", c_ulong),
                ("Data2", c_ushort),
                ("Data3", c_ushort),
                ("Data4", c_ubyte * 8)]

class SP_DEVINFO_DATA(Structure):
    _fields_ = [("cbSize", DWORD),
            ("ClassGuid", GUID),
            ("DevInst", DWORD),
            ("Reserved", c_void_p)
            ]

GUID_DEVCLASS_DISPLAY = GUID(0x4d36e968L, 0xe325, 0x11ce, (c_ubyte*8)(0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18))

DeviceInfoData = SP_DEVINFO_DATA()
hDevInfo = SetupDiGetClassDevs(NULL, #byref(GUID_DEVCLASS_DISPLAY)
        0, # here we can use create_unicode_buffer('PCI') or create_unicode_buffer('USB')
        0,
        DIGCF_PRESENT | DIGCF_ALLCLASSE)

if hDevInfo == INVALID_HANDLE_VALUE:
    exit(1)
print GetLastError(), FormatError()

DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA)
for i in range(10000):
    if not SetupDiEnumDeviceInfo(hDevInfo, i, byref(DeviceInfoData)):
        break
    DataT = DWORD()
    buff = create_unicode_buffer(0)
    buff_lenth = DWORD(0)
    while not SetupDiGetDeviceRegistryProperty(
            hDevInfo,
            byref(DeviceInfoData),
            SPDRP_DEVICEDESC,
            byref(DataT),
            byref(buff),
            buff_lenth,
            byref(buff_lenth)):
        if GetLastError() == ERROR_INSUFFICIENT_BUFFER:
            buff = create_unicode_buffer(buff_lenth.value)
        else:
            print FormatError()
            break
    print u"Device: {}".format(buff.value)
    while not SetupDiGetDeviceRegistryProperty(
            hDevInfo,
            byref(DeviceInfoData),
            SPDRP_HARDWAREID,
            byref(DataT),
            byref(buff),
            buff_lenth,
            byref(buff_lenth)):
        if GetLastError() == ERROR_INSUFFICIENT_BUFFER:
            buff = create_unicode_buffer(buff_lenth.value)
        else:
            #print FormatError()
            print ''
            break
    else:
        print u"HardwareID: {}\n".format(buff.value)

if GetLastError() != NO_ERROR and GetLastError() != ERROR_NO_MORE_ITEMS:
    print FormatError()
    exit(1)
    
SetupDiDestroyDeviceInfoList(hDevInfo)

